use crate::protocol::{RespParser, RespEncoder, RespValue, ProtocolError};
use crate::storage::Storage;
use crate::commands::CommandExecutor;
use bytes::BytesMut;
use std::sync::Arc;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;
use tracing::{debug, error};

/// Client connection handler
pub struct Connection {
    stream: TcpStream,
    buffer: BytesMut,
    storage: Arc<Storage>,
    executor: CommandExecutor,
}

impl Connection {
    /// Create a new connection
    pub fn new(stream: TcpStream, storage: Arc<Storage>) -> Self {
        let executor = CommandExecutor::new(storage.clone());

        Self {
            stream,
            buffer: BytesMut::with_capacity(4096),
            storage,
            executor,
        }
    }

    /// Handle the connection
    pub async fn handle(&mut self) -> Result<(), Box<dyn std::error::Error>> {
        loop {
            // Read data from client
            let bytes_read = self.stream.read_buf(&mut self.buffer).await?;

            if bytes_read == 0 {
                // Client disconnected
                break;
            }

            // Process all complete commands in the buffer
            while let Some(value) = RespParser::parse(&mut self.buffer)? {
                debug!("Received RESP value: {:?}", value);

                match self.process_command(value).await {
                    Ok(response) => {
                        self.send_response(response).await?;
                    }
                    Err(e) => {
                        let error_response = RespValue::error(format!("ERR {}", e));
                        self.send_response(error_response).await?;
                    }
                }
            }
        }

        Ok(())
    }

    /// Process a single command
    async fn process_command(&mut self, value: RespValue) -> Result<RespValue, ProtocolError> {
        let command = RespParser::parse_command(value)?;
        debug!("Executing command: {:?}", command);

        Ok(self.executor.execute(command).await)
    }

    /// Send response to client
    async fn send_response(&mut self, response: RespValue) -> Result<(), Box<dyn std::error::Error>> {
        let encoded = RespEncoder::encode(&response)?;
        self.stream.write_all(&encoded).await?;
        Ok(())
    }
}